package com.chaos.framework.model.serivce;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.function.Function;
import java.util.function.Supplier;

@Service
@RequiredArgsConstructor
public class RedissonLockService {

    private final RedissonDistributedLock redissonDistributedLock;

    /**
     * 执行带分布式锁的无参函数
     * @param lockKey 锁的键
     * @param lockSeconds 锁的超时时间(秒)
     * @param function 要执行的函数
     * @param defaultValue 锁获取失败时的默认值
     * @param <R> 返回值类型
     * @return 函数执行结果或默认值
     */
    public <R> R executeWithLock(String lockKey, int lockSeconds, Supplier<R> function, R defaultValue) {
        Function<Void, R> adapter = unused -> function.get();

        return RedisLockedFunction.<Void, R>builder()
                .redisBean(redissonDistributedLock)
                .redisKey(lockKey)
                .lockSeconds(lockSeconds)
                .showInfoLog(true)
                .function(adapter)
                .build()
                .apply(null, defaultValue);
    }

    /**
     * 执行带分布式锁的有参函数
     * @param lockKey 锁的键
     * @param lockSeconds 锁的超时时间(秒)
     * @param function 要执行的函数
     * @param parameter 函数参数
     * @param defaultValue 锁获取失败时的默认值
     * @param <T> 参数类型
     * @param <R> 返回值类型
     * @return 函数执行结果或默认值
     */
    public <T, R> R executeWithLock(String lockKey, int lockSeconds, Function<T, R> function, T parameter, R defaultValue) {
        return RedisLockedFunction.<T, R>builder()
                .redisBean(redissonDistributedLock)
                .redisKey(lockKey)
                .lockSeconds(lockSeconds)
                .showInfoLog(true)
                .function(function)
                .build()
                .apply(parameter, defaultValue);
    }

    /**
     * 执行带分布式锁的无返回值操作
     * @param lockKey 锁的键
     * @param lockSeconds 锁的超时时间(秒)
     * @param runnable 要执行的操作
     * @param defaultValue 锁获取失败时的默认值
     * @param <R> 返回值类型
     * @return 默认值
     */
    public <R> R executeWithLock(String lockKey, int lockSeconds, Runnable runnable, R defaultValue) {
        Function<Void, R> adapter = unused -> {
            runnable.run();
            return defaultValue; // 对于无返回值操作，执行后返回默认值
        };

        return RedisLockedFunction.<Void, R>builder()
                .redisBean(redissonDistributedLock)
                .redisKey(lockKey)
                .lockSeconds(lockSeconds)
                .showInfoLog(true)
                .function(adapter)
                .build()
                .apply(null, defaultValue);
    }
}